Porting the EDK to other platforms
----------------------------------

About 90% of the components in the EDK are platform independent. They should compile with every ANSI C++ compiler which provides templates, RTTI and exception handling.




To keep the EDK platform independent, you should not change files outside the Platforms directory. Two exceptions are:

- if a file doesn't compile, you can add

- if your compiler supports it, you may implement the time critical parts in inline assembler to get a faster emulation. Search for the string ASMx86 to see which parts of the code are time critical.











If the target platform is a Pentium processor, the label P5ASM can be defined in either EDK.h or the make file:

  #define P5ASM __asm

  #ifdef P5ASM
    P5ASM {
      mov EAX,...
    }
  #else
    // C++ code
  #endif

When P5ASM is defined, some time critical code in the CPU65xx, VIC656x and Timer class is replaced with inline assembler. This improves the overall performance by 15%.

































1.1. Compatibility versus speed
-------------------------------

Emulators are somewhat different from other computer programs. If a


Although there exist


Although in my opinion, speed is not so important as compatibility because computers are getting faster by time.














ClockedInput + ClockedObject -> Chip
ClockedOutput -> CPU
EDK\Include
EDK\Include\Win32










2. Basic components
-------------------


See "Line.h" for a list of functions which the Line class provides.




See "Port.h" for a list of functions which the Port class provides.



2.3. Timers
-----------


See "Timer.h" for a list of functions which the Timer class provides.


2.4. Chips
----------




2.5. Clocks
-----------





       .--------------- Next Clock ---------------.                       x
       v                                          |                         x
   .-------.   .--------.   .--------.   .---------.   .---+---.       x
   | Clock |-->| Chip 1 |-->| Chip 2 |-->| Write 1 |-->| Clock |    x
   '-+-----'   '--------'   '--------'   '---------'   '-------'    x
     |   ^                                                                  x
     v   |                                                                  x
   .-----+-.                     .---------+------.                         x
   |Timers |                     | Delayed Writes |                         x
   '-------'                     '----------------'                         x
                                                                            x
       .-----.      .-----.      .-----.                                    x
  .--> | CPU | ---> | CIA | ---> | VIC | ---.
  |    '-----'      '-----'      '-----'    |
  |              .------------.             |
  '------------- | Next Clock | <-----------'
                 '------------'








// A ClockedObject gets called at each system clock. Implementing the 
// system clock with an o2 Line would be too slow. The task switching
// between ClockedChips is working the following way:
//
//   __declspec(naked) static void FirstClock() {
//     __asm {
//       //
//       // perform action for clock 1 here, ESI means 'this'
//       //
//       mov [ESI]ClockedChip.pfnContinue,offset Clock2
//       mov ESI,[ESI]ClockedChip.pNextClockedObject
//       jmp [ESI]CClockedChip.pfnContinue
//
//     Clock2:
//       //
//       // perform action for clock 2 here, ESI means 'this'
//       //
//       mov [ESI]ClockedChip.pfnContinue,offset Clock3
//       mov ESI,[ESI]ClockedChip.pNextClockedObject
//       jmp [ESI]CClockedChip.pfnContinue
//
//     Clock3:
//       .
//       .
//       .
//     }
//   }
//
// All ClockedObjects are linked together in a circular list. The Clock
// object which generates the clock is also part of this list. In the
// current implementation, the VIC performs the task of the Clock to gain
// more speed. For the same reason, you may not modify EDI within the
// ClockedObject chain because it holds the counter for active Timers.
// Future versions of the EDK will allow several Clocks at different speed
// and use Clock::iTime instead of EDI.
//
// __Declspec(naked) means that the function doesn't have a prolog or epilog.
// There is no final 'ret' and also no space reserved for local variables!
//
// Note that ALL REGISTERS except ESI will be DESTROYED between the code in
// clock 1 and clock 2! Calling C++ functions will destroy EAX/ECX/EDX but
// preserve EBX/ESI/EDI. Adding EBX to the list of preserved registers was
// new in Visual C++ 32 bit, so you may check old asm code for preserving EBX.
//
// There is a bug in MSVC4 which doesn't allow to access member variables
// from inline assembler. Here is a workaround:
//
//   extern MyClockedObject MSVC4Bug;
//   mov EAX,[ESI]MSVC4Bug.iMemberVar
//
// This will add the offset of MyClockedObject::iMemberVar to ESI. Do not
// use MSVC4Bug.iMemberVar[ESI], because this it will add ESI to
// MSVC4Bug.iMemberVar!







   name     size sign
-------------------------
i  int       i   signed
c  char      1   signed
s  short     2   signed
l  long      4   signed

u  unsigned  i   unsigned
b  byte      1   unsigned
w  word      2   unsigned
dw dword     4   unsigned
qw qword     8   unsigned

f  flag      i   signed
e  enum      i   signed
h  handle    i   signed

r  double    8   float

p  pointer   i
a  array
g  global

d
j
k
m
n
o
t
v
x
y
z








